package com.taint.logger;

import com.taint.callgraph.TraceItem;
import com.taint.utils.Utils;

import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TraceLog {
    static final int SIZE = 1024;
    static final String[] queue = new String[1024];

    static final long[] threadIds = new long[1024];
    static final int[] hashCodes = new int[1024];
    static int queueIndex = 0;
    public static FileWriter logWriter = null;
    private static boolean isInit = true;

    static {
        Runtime.getRuntime().addShutdownHook(new TraceLogShutdown());
        Thread.setDefaultUncaughtExceptionHandler(new TraceLogExceptionHandler());
    }

    public static void Init() {
        String logFilePath = "/tmp/agent/taint-agent.log";
        Utils.isExist(logFilePath);
        try {
            logWriter = new FileWriter(logFilePath, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        isInit = false;
    }

    public static void flush() {
        String[] arrayOfString = queue;
        try {
            StringBuilder stringBuilder = new StringBuilder();
            for (byte b = 0; b < queueIndex; b++) {
                stringBuilder.append(queue[b]);
                stringBuilder.append(":");
                stringBuilder.append(threadIds[b]);
                if (hashCodes[b] != 0) {
                    stringBuilder.append(":");
                    stringBuilder.append(hashCodes[b]);
                }
                stringBuilder.append("-");
            }
        } catch (Exception e) {

        }
    }

    public static TraceEntry NewTraceEntry(TraceEndpoint methodEntry, TraceItem stackItem, Object[] args) {

        String uuid = "uuid-test";
        TraceEntry entry = new TraceEntry(methodEntry, stackItem, uuid);
        //这里判断下args 是否为空
        if (null == args || args.length == 0) {
            entry.arguments = null;
        } else {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < args.length; i++) {
                sb.append(args[i]).append(" ");
            }
            entry.arguments = sb.toString();
        }

        return entry;
    }

    public static void Log(TraceEntry traceEntry){
        if(traceEntry!=null){
            addTog(traceEntry);
        }
    }

    public static void Log(TraceEndpoint methodEntry, TraceItem stackItem, Object[] args) {

        String uuid = "uuid";
        TraceEntry entry = new TraceEntry(methodEntry, stackItem, uuid);

        //这里判断下args 是否为空
        if (null == args || args.length == 0) {
            entry.arguments = null;
        } else {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < args.length; i++) {
                sb.append(args[i]).append(" ");
            }
            entry.arguments = sb.toString();
        }

        addTog(entry);


    }

    private static void addTog(TraceEntry entry) {
        if (isInit) {
            Init();
        }

        //时间
        String returnString = entry.traceItem.getReturned() != null ? entry.traceItem.getReturned().toString() : "null";
        String log = String.format("[%s] %s %s %s [routes:%s] %s.%s%s args: %s stack: %s return: %s\r\n", entry.traceEndpoint, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), entry.threadName, entry.threadId,
                entry.traceItem.getRoutes(), entry.traceItem.getClassName(), entry.traceItem.getMethodName(), entry.traceItem.getDesc(), entry.arguments, entry.traceItem.getStacktrace(), returnString);

        synchronized (logWriter) {
            try {
                logWriter.write(log);
                logWriter.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }
}
